package util;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

import model.BalanceObjective;
import model.Machine;
import model.Problem;
import model.Process;
import model.Resource;
import model.Service;

public class Importer {
	String problemFileName;
	Problem problem;

	public Importer(String fn) {
		problemFileName = fn;
		problem = new Problem();
	}

	public Problem getProblem() {
		return problem;
	}

	public void readData() {
		try {
			BufferedReader in = new BufferedReader(new FileReader(
					problemFileName));
			String str;
			String status = "RESOURCES";
			int r = 0, m = 0, se = 0, p = 0, b = 0;
			while ((str = in.readLine()) != null) {
				str = str.trim();
				String s[] = str.split("\\s+");
				if (status.equalsIgnoreCase("RESOURCES")) {
					r = Integer.parseInt(s[0]);
					status = "RESOURCES_DATA";
				} else if (status.equalsIgnoreCase("RESOURCES_DATA")) {
					Resource resource = new Resource();
					resource.setTransientUsage(s[0].equalsIgnoreCase("0") ? false
							: true);
					resource.setWeightLoadCost(Integer.parseInt(s[1]));
					problem.addResource(resource);
					if (problem.getResources().size() == r) {
						status = "MACHINES";
					}
				} else if (status.equalsIgnoreCase("MACHINES")) {
					m = Integer.parseInt(s[0]);
					status = "MACHINES_DATA";
				} else if (status.equalsIgnoreCase("MACHINES_DATA")) {
					Machine machine = new Machine();
					machine.setNeighborhood(Integer.parseInt(s[0]));
					machine.setLocation(Integer.parseInt(s[1]));
					for (int i = 0; i < r; i++) {
						Resource resource = problem.getResourceByIndex(i);
						machine.addCapacity(resource.getId(),
								Integer.parseInt(s[2 + i]));
						machine.addSafetyCapacity(resource.getId(),
								Integer.parseInt(s[2 + r + i]));
					}
					for (int i = 0; i < m; i++) {
						machine.addMachineMoveCost("m" + i,
								Integer.parseInt(s[2 + r + r + i]));
					}
					problem.addMachine(machine);
					if (problem.getMachines().size() == m) {
						status = "SERVICES";
					}
				} else if (status.equalsIgnoreCase("SERVICES")) {
					se = Integer.parseInt(s[0]);
					status = "SERVICES_DATA";
				} else if (status.equalsIgnoreCase("SERVICES_DATA")) {
					Service service = new Service();
					service.setSpreadMin(Integer.parseInt(s[0]));
					int dos = Integer.parseInt(s[1]);
					for (int i = 0; i < dos; i++) {
						service.addDependsOn(i);
					}
					problem.addService(service);
					if (problem.getServices().size() == se) {
						status = "PROCESSES";
					}
				} else if (status.equalsIgnoreCase("PROCESSES")) {
					p = Integer.parseInt(s[0]);
					status = "PROCESSES_DATA";
				} else if (status.equalsIgnoreCase("PROCESSES_DATA")) {
					Process process = new Process();
					process.setService(Integer.parseInt(s[0]));
					for (int i = 0; i < r; i++) {
						process.addRequirement("r" + i,
								Integer.parseInt(s[1 + i]));
					}
					process.setProcessMoveCost(Integer.parseInt(s[r + 1]));
					problem.addProcess(process);
					if (problem.getProcesses().size() == p) {
						status = "BALANCE_OBJECTIVES";
					}
				} else if (status.equalsIgnoreCase("BALANCE_OBJECTIVES")) {
					b = Integer.parseInt(s[0]);
					if (b > 0)
						status = "BALANCE_OBJECTIVES_DATA";
					else
						status = "WEIGHTS";
				} else if (status.equalsIgnoreCase("BALANCE_OBJECTIVES_DATA")) {
					BalanceObjective bo = new BalanceObjective();
					bo.resource1 = "r" + s[0];
					bo.resource2 = "r" + s[1];
					bo.target = Integer.parseInt(s[2]);
					str = in.readLine();
					str = str.trim();
					s = str.split("\\s+");
					bo.weightBalanceCost = Integer.parseInt(s[0]);
					problem.addBalanceObjective(bo);
					if (problem.getBalanceObjectives().size() == b) {
						status = "WEIGHTS";
					}
				} else if (status.equalsIgnoreCase("WEIGHTS")) {
					problem.setWeightProcessMoveCost(Integer.parseInt(s[0]));
					problem.setWeightServiceMoveCost(Integer.parseInt(s[1]));
					problem.setWeightMachineMoveCost(Integer.parseInt(s[2]));
					status = "END";
				} else {
					System.out.println("UNKNOWN " + str);
				}
			}
			in.close();
			problem.generateDataStructures();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}
